/* eslint-disable no-bitwise */
/* eslint-disable no-param-reassign */
/* eslint-disable no-plusplus */
/* eslint-disable no-mixed-operators */
/* global window */
import Base from 'base'; // eslint-disable-line

function rotatePoint(p, c, theta) {
  const [px, py] = p;
  if (!theta) return [px, py];
  const [cx, cy] = c;
  const rx = px - cx;
  const ry = py - cy;
  const rad = theta * Math.PI / 180;
  const cos = Math.cos(rad);
  const sin = Math.sin(rad);
  const nx = rx * cos - ry * sin;
  const ny = rx * sin + ry * cos;
  return [nx + cx, ny + cy];
}

export default Base.Model.extend({
  defaults: {
    widgetName: 'pendulumTriangle',

    // user customized data
    materials: [],
    preset: { images: [] ,answer:0 },
    recordStrokes: false,
    isEditMode: false,
    defaultMode: 'move',
    defaultDrawMode: 'free',
    defaultLineDash: 'solid',
    defaultStrokeColor: '#000000',
    defaultStrokeWidth: 4,
    snapImage: false,
    widgetWidth: 0,
    widgetHeight: 0,

    // internal data
    initialImages: [], // 图片的初始状态
    images: [], // 用户操作后的图片状态
    answer:[],
    operations: [], // 用户的操作记录，不包括 undo/redo 记录
    allOperations: [], // 用户的操作记录，包括 undo/redo 记录
    editMode: '',
    mode: 'move',
    historyIndex: -1,
    recordStrokeLeft: 0,
    recordStrokeTop: 0,
    isCommonPoint:false,
    clickPoint:[],
    trianglesPoint:[],
    circleLocation:[],
    drawing:{}
  },

  initialize() {
    this.initData();
  },

  initData() {
    this.set('fullPath', this.get('fullPath').replace(/\/+$/, ''));
    try {
      let preset = this.get('preset');
      if (typeof preset === 'string') {
        preset = JSON.parse(decodeURIComponent(window.atob(this.get('preset'))));
      }else {
        preset = JSON.parse(JSON.stringify(preset));
      }
      const { images } = preset;
      images.forEach((img) => {
        if (typeof img.originX === 'undefined') {
          img.originX = 50;
        }
        if (typeof img.originY === 'undefined') {
          img.originY = 50;
        }
      });
      this.set('images', images);
    
      this.set('initialImages', JSON.parse(JSON.stringify(images)));
      this.set('operations', []);
      this.set('allOperations', []);
      this.set('historyIndex', -1);
    } catch (e) {
      this.set('images', []);
      console.error(e);
    }
  },

  stepBack() {
    const historyIndex = this.get('historyIndex');
    if (historyIndex !== -1) {
      this.set('historyIndex', historyIndex - 1);
      const allOperations = this.get('allOperations');
      allOperations.push({ type: 'undo' });
    }
  },
  stepForward() {
    const historyIndex = this.get('historyIndex');
    const operations = this.get('operations');
    if (historyIndex < (operations.length - 1)) {
      this.set('historyIndex', historyIndex + 1);
      const allOperations = this.get('allOperations');
      allOperations.push({ type: 'redo' });
    }
  },

  addImageMovement() {
    const operations = this.get('operations');
    const data = this.get('images').map(img => ({
      mi: img.materialIndex,
      d: (img.draggable ? 1 : 0) |
        (img.infiniteDrag ? 2 : 0) |
        (img.rotatable ? 4 : 0) |
        (img.rotateBtnVisible ? 8 : 0),
      t: Math.round(img.top),
      l: Math.round(img.left),
      w: Math.round(img.width),
      h: Math.round(img.height),
      r: img.rotation ? Math.round(img.rotation) : 0,
      rs: img.rotateStep || 15,
      ox: img.originX,
      oy: img.originY,
      iv: !!img.hidden,
      g: img.group,
    })); // snapshot image's pos and size
    const recordStrokeData = {
      t: Math.round(this.get('recordStrokeTop')),
      l: Math.round(this.get('recordStrokeLeft'))
    };
    const historyIndex = this.get('historyIndex');
    if (historyIndex !== operations.length - 1) {
      while (operations.length > historyIndex + 1) operations.pop();
    }
    let operation;
    if(this.get('recordStrokes')){
      operation = { type: 'moveImage', data,recordStrokeData, t: Date.now() };
    }else{
      operation = { type: 'moveImage', data, t: Date.now() };
    }
    operations.push(operation);
    const allOperations = this.get('allOperations');
    allOperations.push(operation);
    this.set('historyIndex', operations.length - 1);
  },
  // undo/redo 时根据当前所在的步骤获取图片的状态
  getImages() {
    const materials = this.get('materials');
    const operations = this.get('operations');
    const historyIndex = this.get('historyIndex');
    for (let i = historyIndex; i >= 0; i--) {
      const { type, data } = operations[i];
      if (type === 'moveImage') {
        // recover images snapshot
        return data.map(img => ({
          materialIndex: img.mi,
          draggable: !!(img.d & 1),
          infiniteDrag: !!(img.d & 2),
          rotatable: !!(img.d & 4),
          rotateBtnVisible: !!(img.d & 8),
          rotateStep: img.rs || 15,
          top: img.t,
          left: img.l,
          width: img.w,
          height: img.h,
          rotation: img.r || 0,
          originX: typeof img.ox === 'number' ? img.ox : 50,
          originY: typeof img.oy === 'number' ? img.oy : 50,
          image: materials[img.mi] ? materials[img.mi].image : '',
          group: img.g,
          hidden: !!img.iv,
        }));
      }
    }
    return JSON.parse(JSON.stringify(this.get('initialImages')));
  },

  addStroke(stroke) {
    const operations = this.get('operations');
    const historyIndex = this.get('historyIndex');
    if (historyIndex !== operations.length - 1) {
      while (operations.length > historyIndex + 1) operations.pop();
    }
    const operation = { type: 'stroke', data: stroke, t: Date.now() };
    operations.push(operation);
    const allOperations = this.get('allOperations');
    allOperations.push(operation);
    this.set('historyIndex', operations.length - 1);
  },

  getStrokes() {
    const operations = this.get('operations');
    const historyIndex = this.get('historyIndex');
    const strokes = [];
    for (let i = 0; i <= historyIndex; i++) {
      const { type, data } = operations[i];
      if (type === 'stroke') strokes.push(data);
    }
    return strokes;
  },

  addImage(materialIndex) {
    const images = this.get('images');
    const materials = this.get('materials');
    images.push({
      materialIndex,
      draggable: false,
      infiniteDrag: false,
      rotatable: false,
      rotateBtnVisible: false,
      isResizer: false,
      equalProportion: false,
      rotateStep: 15,
      top: 0,
      left: 0,
      width: 100,
      height: 100,
      rotation: 0,
      originX: 50,
      originY: 50,
      image: materials[materialIndex].image,
      group: '',
      hidden: false,
    });
  },

  /**
   * 计算所有图片的边框各顶点坐标，考虑旋转的情况
   */
  getImageRects() {
    const images = this.get('images');
    const rects = [];
    images.forEach((image) => {
      const rect = [
        [image.left, image.top],
        [image.left + image.width, image.top],
        [image.left + image.width, image.top + image.height],
        [image.left, image.top + image.height]
      ];
      if (image.rotation) {
        const center = [image.left + image.originX * image.width / 100, image.top + image.originY * image.height / 100];
        rects.push(rect.map(p => rotatePoint(p, center, image.rotation)));
      } else {
        rects.push(rect);
      }
    });
    return rects;
  },

  getImageRect(imageData) {
    const rect = [
      [imageData.left, imageData.top],
      [imageData.left + imageData.width, imageData.top],
      [imageData.left + imageData.width, imageData.top + imageData.height],
      [imageData.left, imageData.top + imageData.height]
    ];
    if (imageData.rotation) {
      const center = [
        imageData.left + imageData.originX * imageData.width / 100,
        imageData.top + imageData.originY * imageData.height / 100
      ];
      return rect.map(p => rotatePoint(p, center, imageData.rotation));
    }
    return rect;
  },

  removeImage(imageIndex) {
    const images = this.get('images');
    images.splice(imageIndex, 1);
    images.forEach((image, i) => {
      image.answerIndex = i;
    });
  },

  getElementData(type, index) {
    if (type === 'image') {
      return this.get('images')[index];
    }
    return null;
  },

});
